package cn.tedu.knows.search.interceptor;

import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;

// @Component是必须写的!!!!
@Component
public class AuthInterceptor implements HandlerInterceptor {

    @Resource
    private RestTemplate restTemplate;
    // 在控制器方法运行之前就要解析jwt
    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response, Object handler) throws Exception {
        // 从请求中获得jwt
        String token=request.getParameter("accessToken");
        // 定义Ribbon的url
        String url="http://auth-service/oauth/check_token?token={1}";
        // 我们可以使用Map类型来接收Ribbon的结果
        // Ribbon内部会自动将json对象解析为键值对赋值给Map对象
        Map<String,Object> map=restTemplate.getForObject(
                url,Map.class,token);
        // 根据auth测试结果观察,我们只需要用户名和用户权限
        // 用户名user_name 用户权限authorities
        String username=map.get("user_name").toString();
        List<String> list=(List<String>)map.get("authorities");
        // 下面需要将用户信息保存到Spring-Security中
        // 因为Spring-Security框架是安全框架,代码严谨所以我们必须按照
        // 固定的方式向Spring-Security框架中保存用户信息
        // 将保存在List中的权限转换为String[]
        String[] auth=list.toArray(new String[0]);
        UserDetails details= User.builder()
                .username(username)
                .password("")
                .authorities(auth)
                .build();
        // 获得了用户详情,下面需要按照Spring-Security给定的方式
        // 将用户详情保存到Spring-Security中
        PreAuthenticatedAuthenticationToken authenticationToken=
                new PreAuthenticatedAuthenticationToken(
                        details,
                        details.getPassword(),
                        AuthorityUtils.createAuthorityList(auth)
                );
        // 和当前请求request对象进行关联
        authenticationToken.setDetails(
                new WebAuthenticationDetails(request));
        // 将用户详情对象保存到Spring-Security容器
        SecurityContextHolder.getContext()
                .setAuthentication(authenticationToken);
        // 千万别忘了返回true!!!!!!!
        return true;
    }
}



